iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
自我挑戰組

Hello SQL 初次見面你好系列 第 9

Day 9 SQL 的約束 (Constraint) (上)

  • 分享至 

  • xImage
  •  

在前幾天的文章中,我們在示範 CREATE TABLE 時,常常會看到在定義欄位時常會出現 PRIMARY KEY, NOT NULL 那這些都是 SQL 中的約束 (Constraint)

何謂約束 (Constraint)

約束用於限定 資料表 中的資料,可以保證了資料的準確性和可靠性
約束可以在創建資料表的時(CREATE TABLE) 或在資料表建立後使用 ALTER TABLE 來定義

今天就讓我們來介紹 SQL 中的約束 (Constraint) 有哪些類型,並如何通過 CREATE TABLE 或是 ALTER TABLE 來定義我們的資料表約束 (Constraint)

1. PRIMARY KEY 約束

PRIMARY KEY: Primary Key 稱為 主鍵,用來約束唯一標識資料表中的每一條記錄,一個資料表只能有一個主鍵,且主鍵的值必須是唯一的,不能有重複,也不能為 NULL

範例:

CREATE TABLE users (
    id SERIAL PRIMARY KEY
);
  • SERIAL 是 PostgreSQL 中的一種特殊的數據類型,用於自動生成的整數。

這時我們將 users table 的設定顯示出來

-- 使用 \d 語法
demo_db=# \d users

                            Table "public.users"
 Column |  Type   | Collation | Nullable |              Default
--------+---------+-----------+----------+-----------------------------------
 id     | integer |           | not null | nextval('users_id_seq'::regclass)
 
Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
  • 在上面我們可以看到 id 欄位的資料型態為 integer 且不能為 null
  • 這邊我們有看到 Default 為 nextval('users_id_seq'::regclass)
  • 也就是他會去找 users_id_seq 的 last_value 欄位

2. UNIQUE 約束

UNIQUE: 確保在一個資料表中的所以每一列資料的某一欄位的值都是唯一的

CREATE TABLE posts (
    title VARCHAR (50) UNIQUE
);

一樣使用 \d table_name 將 posts table 印出來

demo_db=# \d posts
                      Table "public.posts"
 Column |         Type          | Collation | Nullable | Default
--------+-----------------------+-----------+----------+---------
 title  | character varying(50) |           |          |

Indexes:
    "posts_title_key" UNIQUE CONSTRAINT, btree (title)
  • 我們看的到了 "posts_title_key" UNIQUE CONSTRAINT, btree (title) 我們幫 title 欄位加上了 UNIQUE CONSTRAINT
  • 會加上 INDEX 是因為 PostgreSQL 能夠快速確定一個值是否已經存在於表中,所以它使用索引來加速這個查找過程

所以這時我們來測試一下,先寫入一筆資料,再寫入相同的一筆,來看看會發生什麼事情

-- 第一次寫入
INSERT INTO posts (title) VALUES ('我是一本書') RETURNING *;

   title
------------
 我是一本書
(1 row)

INSERT 0 1 -- 成功的 INSERT 了

-- 第二次寫入一樣的資料
INSERT INTO posts (title) VALUES ('我是一本書') RETURNING *;

ERROR:  duplicate key value violates unique constraint "posts_title_key"
DETAIL:  Key (title)=(我是一本書) already exists.

我們可以看到寫入第二筆資料時,會發生錯誤因為 Key (title)=(我是一本書) 已經存在了
所以我們可以知道 unique constraint 起作用了

3. NOT NULL 約束

NOT NULL: 確保在資料表中在設定欄位中不能有 NULL 值,即必須含有資料

 CREATE TABLE members ( 
     name varchar(60) NOT NULL
 );
demo_db=# \d members


                     Table "public.members"
 Column |         Type          | Collation | Nullable | Default
--------+-----------------------+-----------+----------+---------
 name   | character varying(60) |           | not null |

這就就相對好懂一點,我們可以看到 在 members table 資訊中 Nullable 可以允許使否為 null
這邊顯示 not null 代表不能為 null

一樣來測試一下,嘗試將空的資料寫入

-- 下面兩種寫法都可以,這邊可以使用 DEFAULT VALUES 是因為我們沒有設定 name 的 DEFAULT 所以他為 null
INSERT INTO members (name) VALUES (null);
INSERT INTO members DEFAULT VALUES;


ERROR:  null value in column "name" of relation "members" violates not-null constraint
DETAIL:  Failing row contains (null).

4. DEFAULT 約束

DEFAULT: 用於幫欄位設定默認值,如果寫入一筆資料,但是在設定有默認值的欄位填上值的話,則會使用默認值

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    status VARCHAR (50) DEFAULT 'Pending'
);

一樣列出 orders 資料表的資訊

demo_db=# \d orders
                                   Table "public.orders"
 Column |         Type          | Collation | Nullable |              Default
--------+-----------------------+-----------+----------+------------------------------------
 id     | integer               |           | not null | nextval('orders_id_seq'::regclass)
 status | character varying(50) |           |          | 'Pending'::character varying
Indexes:
    "orders_pkey" PRIMARY KEY, btree (id)

我們可以看到在 Default 欄位中 status 的設定為 Pending

我們來驗證一下


INSERT INTO orders (status) VALUES ('Paid'), (DEFAULT) RETURNING *;

 id | status
----+---------
 1  | Paid
 2  | Pending
(2 rows)

INSERT 0 2

我們可以看到我們在寫入第二筆 order 資料時,我們添入了 DEFAULT,所以在 orders table 會呈現 Pending

結語

今天我們介紹了什麼是 SQL 中的 Constraint,並先介紹其中的 Primary Key Unique Not Null DEFAULT
明天會繼續將剩下的部分,講完,感謝大家收看


上一篇
DAY 8 什麼是 DDL、DML、TCL、DCL
下一篇
Day 10 SQL 的約束 (Constraint)(下)
系列文
Hello SQL 初次見面你好30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言